iT邦幫忙

2024 iThome 鐵人賽

DAY 24
1
JavaScript

不會 VueUse 而被提分手的我系列 第 24

D-24 useWebWorkerFn 文件說明與範例 - 忍術替身術

  • 分享至 

  • xImage
  •  

學習的過程中,我不斷思考,這種分工合作的方式,其實跟生活中的許多事情相似。有時候,我們總會陷入單一任務的泥沼,無法分身去處理其他重要的事。而 useWebWorkerFn 正好解決了這個問題,把那些耗時但必要的工作分給其他執行緒處理。
https://ithelp.ithome.com.tw/upload/images/20241007/20162115CkNF0X3o7E.png

前情提要

useWebWorkerFn 是 VueUse 中用於在 Web Worker 中執行大量複雜運算的工具。本文將詳細介紹其功能、參數和使用場景,並提供實用範例。
可以參考【Web微知識系列】 Web Workers 先了解 worker 的基本知識再回來看會比較清楚喔!

useWebWorkerFn API

功能

useWebWorkerFn 用於將繁重的計算任務移出主線程,並通過 Web Worker 在背景中執行。它封裝了 Web Worker 的建立、運行和終止邏輯,並以 Promise 形式返回結果,確保應用的 UI 不會因為計算而被阻塞。特別適用於需要大量計算、但又不希望影響應用流暢性的場景,例如:圖片處理、大量的資料計算等等。

Props

名稱 類型 說明
fn T extends (...fnArgs: any[]) => any 需要在 Web Worker 中執行的函式。
options UseWebWorkerOptions 可選參數,用於配置 Web Worker 的行為。

options 參數

名稱 類型 默認值 說明
timeout number undefined 設置 Worker 的最大存活時間(毫秒)。超過該時間後,Worker 將自動終止。
dependencies string[] [] 外部依賴的腳本 URL,用於 Worker 中需要的外部資源。
localDependencies Function[] [] 本地依賴函式,用於 Worker 中所需的本地定義。

返回值

useWebWorkerFn 返回一個包含以下屬性的對象:

名稱 類型 說明
workerFn (...fnArgs: Parameters<T>) => Promise<ReturnType<T>> 將函式在 Web Worker 中執行的函數,返回一個 Promise,包含執行結果。
workerStatus Ref<WebWorkerStatus> Web Worker 當前的狀態,包括 PENDINGRUNNINGSUCCESSERRORTIMEOUT_EXPIRED
workerTerminate (status?: WebWorkerStatus) => void 手動終止 Web Worker 的函數,用於清理資源。

WebWorkerStatus Enum

名稱 說明
PENDING Worker 函數尚未執行。
RUNNING Worker 函數正在執行。
SUCCESS Worker 執行成功並返回結果。
ERROR Worker 執行失敗並捕獲錯誤。
TIMEOUT_EXPIRED Worker 因超時而終止。

用法範例

範例 1:基本用法

點擊玩玩看

以下是一個基本用法範例,展示如何使用 useWebWorkerFn 來計算大量資料,避免阻塞主線程。

<template>
	 <div class="p-5">
	    <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" @click="runTask">點擊開始計算任務</button>
	    <p v-if="workerStatus === 'RUNNING'">計算中...</p>
	    <p v-if="result !== null">計算結果: {{ result }}</p>
	    <p v-if="error !== null">錯誤: {{ error }}</p>
	  </div>
  </template>

<script setup>
import { ref } from 'vue'
import { useWebWorkerFn } from '@vueuse/core'

const inputData = ref(1000000)

const {
  workerFn,
  workerStatus,
  workerTerminate
} = useWebWorkerFn((n) => {
  // 計算任務:求和 1 到 n
  let sum = 0
  for (let i = 1; i <= n; i++) {
    sum += i
  }
  return sum
}, { timeout: 5000 })

const result = ref(null)
const error = ref(null)

const runTask = async () => {
  try {
    result.value = await workerFn(inputData.value)
  } catch (e) {
    error.value = e
  }
}
</script>

範例 2:使用超時配置

點擊玩玩看範例

以下範例展示如何設置 Worker 超時時間,避免長時間計算對資源的佔用。

<template>
   <div class="p-5">
    <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" @click="runTask">開始計算(限時 3 秒)</button>
    <p>狀態: {{ workerStatus }}</p>
    <p v-if="resultVal">結果:{{resultVal}}</p>
	</div>
</template>

<script setup>
import { ref } from 'vue'
import { useWebWorkerFn } from '@vueuse/core'

const resultVal = ref()

const {
  workerFn,
  workerStatus
} = useWebWorkerFn((n) => {
  // 長時間計算函數
  let sum = 0
  for (let i = 1; i <= n; i++) {
    sum += Math.sqrt(i)
  }
  return sum
}, { timeout: 3000 })

const runTask = () => {
  resultVal.value = undefined
  workerFn(100000000)
    .then(result => {
      console.log('計算結果:', result)
      resultVal.value = result
    })
    .catch(err => console.error('計算失敗:', err))
}
</script>

useWebWorkerFn 的使用場景

  1. 計算密集型任務:例如處理大量資料的計算,避免阻塞主線程,保證 UI 交互的流暢性。
  2. 圖片處理:在前端應用中對圖片進行壓縮、過濾等操作時,利用 Web Worker 可以避免性能瓶頸。
  3. 長時間任務:例如資料加密、解碼等需要較長時間的任務,避免長時間佔用主線程資源。

為什麼開發者需要 useWebWorkerFn

  1. 減少 UI 阻塞:Web Worker 能在背景執行任務,防止計算密集型任務阻塞主線程,從而提升應用的反應速度。
  2. 簡化 Worker 使用useWebWorkerFn 封裝了 Web Worker 的建立和通信邏輯,使得使用 Web Worker 變得更加簡單和直觀。
  3. 靈活配置useWebWorkerFn 支援依賴的傳遞和超時配置,滿足不同的應用場景需求。
  4. 良好的錯誤處理:通過 workerStatus 提供任務的狀態跟蹤,方便開發者對任務的失敗進行處理。

結論

useWebWorkerFn是一個強大而簡單的工具,用於在 Vue 應用中實現計算密集型任務的背景執行。透過簡潔的 API 和豐富的設定選項,開發者可以輕鬆實現高效的前端性能優化。合理運用useWebWorkerFn能大幅減少編寫 Worker 建立和通信的程式碼,同時提升應用性能和程式碼可維護性。(這功能真的超讚!以前每次寫 worker 都得重新翻文件,有了useWebWorkerFn後,媽媽再也不用擔心我看不懂啦!)


上一篇
D-23 useClipboard 解析與動機
下一篇
D-25 useWebWorkerFn 解析與動機 - 研究替身
系列文
不會 VueUse 而被提分手的我30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言